from typing import List, Optional
from sqlalchemy.orm import Session
from fastapi import HTTPException, status
from ..models.module import Module as ModuleModel
from ..schemas.module import ModuleCreate, ModuleUpdate

class ModuleService:
    def __init__(self, db: Session):
        self.db = db

    def get_module(self, module_id: int) -> Optional[ModuleModel]:
        """根据ID获取模块"""
        return self.db.query(ModuleModel).filter(ModuleModel.id == module_id).first()

    def get_module_by_code(self, code: str) -> Optional[ModuleModel]:
        """根据代码获取模块"""
        return self.db.query(ModuleModel).filter(ModuleModel.code == code).first()

    def get_modules(self, skip: int = 0, limit: int = 100) -> List[ModuleModel]:
        """获取所有模块列表"""
        return self.db.query(ModuleModel).offset(skip).limit(limit).all()

    def get_active_modules(self, skip: int = 0, limit: int = 100) -> List[ModuleModel]:
        """获取所有激活的模块"""
        return self.db.query(ModuleModel).filter(ModuleModel.is_active == True).offset(skip).limit(limit).all()

    def create_module(self, module: ModuleCreate) -> ModuleModel:
        """创建新模块"""
        # 检查模块代码是否已存在
        existing_module = self.get_module_by_code(module.code)
        if existing_module:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=f"模块代码 '{module.code}' 已存在"
            )
        
        # 检查父模块是否存在
        if module.parent_id:
            parent_module = self.get_module(module.parent_id)
            if not parent_module:
                raise HTTPException(
                    status_code=status.HTTP_404_NOT_FOUND,
                    detail=f"父模块ID {module.parent_id} 不存在"
                )
        
        db_module = ModuleModel(**module.dict())
        self.db.add(db_module)
        self.db.commit()
        self.db.refresh(db_module)
        return db_module

    def update_module(self, module_id: int, module: ModuleUpdate) -> ModuleModel:
        """更新模块信息"""
        db_module = self.get_module(module_id)
        if not db_module:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail=f"模块ID {module_id} 不存在"
            )
        
        # 检查要更新的模块代码是否已被其他模块使用
        if module.code and module.code != db_module.code:
            existing_module = self.get_module_by_code(module.code)
            if existing_module:
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST,
                    detail=f"模块代码 '{module.code}' 已被使用"
                )
        
        # 检查新的父模块是否存在
        if module.parent_id is not None:
            if module.parent_id == module_id:
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST,
                    detail="模块不能将自身作为父模块"
                )
            parent_module = self.get_module(module.parent_id)
            if not parent_module:
                raise HTTPException(
                    status_code=status.HTTP_404_NOT_FOUND,
                    detail=f"父模块ID {module.parent_id} 不存在"
                )
        
        # 更新模块信息
        for key, value in module.dict(exclude_unset=True).items():
            setattr(db_module, key, value)
        
        self.db.commit()
        self.db.refresh(db_module)
        return db_module

    def delete_module(self, module_id: int) -> None:
        """删除模块"""
        db_module = self.get_module(module_id)
        if not db_module:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail=f"模块ID {module_id} 不存在"
            )
        
        # 检查是否有子模块
        has_children = self.db.query(ModuleModel).filter(ModuleModel.parent_id == module_id).first() is not None
        if has_children:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=f"模块 '{db_module.name}' 存在子模块，无法删除"
            )
        
        self.db.delete(db_module)
        self.db.commit()

    def get_module_tree(self) -> List[ModuleModel]:
        """获取模块树结构（用于管理员界面）"""
        # 获取所有激活的模块
        modules = self.get_active_modules()
        
        # 构建模块树
        module_dict = {module.id: module for module in modules}
        root_modules = []
        
        for module in modules:
            if module.parent_id is None:
                root_modules.append(module)
            else:
                parent = module_dict.get(module.parent_id)
                if parent:
                    if not hasattr(parent, 'children'):
                        parent.children = []
                    parent.children.append(module)
                    # 对子模块按order排序
                    parent.children.sort(key=lambda x: x.order or 0)
        
        # 对根模块按order排序
        root_modules.sort(key=lambda x: x.order or 0)
        
        return root_modules

    def get_admin_modules(self) -> List[ModuleModel]:
        """获取管理员可以访问的所有模块"""
        # 管理员可以访问所有激活的模块
        return self.get_module_tree()